﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

using Microsoft.TeamFoundation.WorkItemTracking.Client;


namespace Qetza.TeamFoundation.WorkItemQuery.Admin
{
    /// <summary>
    /// Command to import a work item query.
    /// </summary>
    public class CommandImportWiq : ICommand
    {
        #region ICommand Members

        /// <inheritdoc />
        public string Name
        {
            get { return "import"; }
        }

        /// <inheritdoc />
        public string HelpText
        {
            get { return ResourceStrings.ImportWiqHelpText; }
        }

        /// <inheritdoc />
        public IEnumerable<ParameterInfo> AllowedParameters
        {
            get
            {
                return new[] {
                   new ParameterInfo() { 
                        Name = CoreArgumentNames.Server, 
                        ArgumentName = ResourceStrings.ServerArgument, 
                        IsRequired = true, 
                        HelpText = ResourceStrings.ServerHelpText
                        },
                    new ParameterInfo() { 
                        Name = CoreArgumentNames.Project, 
                        ArgumentName = ResourceStrings.ProjectArgument, 
                        IsRequired = true, 
                        HelpText = ResourceStrings.ProjectHelpText
                        },
                    new ParameterInfo() {
                        Name = CoreArgumentNames.QueryPath,
                        ArgumentName = ResourceStrings.QueryNameArgument,
                        HelpText = ResourceStrings.Import_QueryNameHelpText
                        },
                    new ParameterInfo() {
                        Name = CoreArgumentNames.File,
                        ArgumentName = ResourceStrings.FileArgument, 
                        IsRequired = true,
                        HelpText = ResourceStrings.Import_FileHelpText
                        },
                    new ParameterInfo() {
                        Name = CoreArgumentNames.Private,
                        IsFlag = true,
                        HelpText = ResourceStrings.PrivateFlagHelpText
                        }
                    };
            }
        }

        /// <inheritdoc />
        public void Execute(IDictionary<string, string> parameters)
        {
            // get query
            var storedQueries = TfsUtility
                .GetWorkItemStore(parameters[CoreArgumentNames.Server], parameters.ContainsKey(CoreArgumentNames.NoPrompt))
                .Projects[parameters[CoreArgumentNames.Project]]
                .StoredQueries;

            if (parameters[CoreArgumentNames.File][0] == '@')
            {
                // import query from file
                using (var file = new System.IO.StreamReader(parameters[CoreArgumentNames.File].Substring(1)))
                {
                    var line = default(string);
                    while ((line = file.ReadLine()) != null)
                    {
                        try
                        {
                            if (!string.IsNullOrEmpty(line))
                            {
                                this.ImportQuery(parameters, line, storedQueries);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ResourceStrings.ErrorImportQuery, line, ex.Message);
                        }
                    }
                }
            }
            else
            {
                // import single query
                this.ImportQuery(parameters, parameters[CoreArgumentNames.File], storedQueries);
            }

            Console.WriteLine(ResourceStrings.ImportWiqCompleted);
        }

        /// <inheritdoc />
        public void ValidateParameters(IDictionary<string, string> parameters)
        {
            if (parameters[CoreArgumentNames.File][0] != '@' && !parameters.ContainsKey(CoreArgumentNames.QueryPath))
            {
                throw new InvalidParameterException(
                    string.Format(ResourceStrings.MissingSwitch, CoreArgumentNames.QueryPath),
                    CoreArgumentNames.QueryPath
                    );
            }

            return;
        }

        #endregion

        #region Private Helpers

        // Replaces know variables in query text.
        private static string ReplaceVariables(string value, IDictionary<string, string> parameters)
        {
            // $$PROJECTNAME$$
            return value.Replace("$$PROJECTNAME$$", parameters[CoreArgumentNames.Project]);
        }

        // Imports a query.
        private void ImportQuery(IDictionary<string, string> parameters, string file, StoredQueryCollection storedQueries)
        {
            var queryText = ReplaceVariables(
                    XDocument.Load(file).Descendants("Wiql").First().Value,
                    parameters
                    );

            // get query
            var query = default(StoredQuery);
            if (parameters[CoreArgumentNames.File][0] == '@')
            {
                query = storedQueries.Find(System.IO.Path.GetFileNameWithoutExtension(file));
            }
            else
            {
                query = storedQueries.Find(parameters[CoreArgumentNames.QueryPath]);
            }

            var queryScope = parameters.ContainsKey(CoreArgumentNames.Private) ? QueryScope.Private : QueryScope.Public;

            if (query == null || query.QueryScope != queryScope)
            {
                // add new query
                query = new StoredQuery(
                    queryScope,
                    parameters[CoreArgumentNames.QueryPath],
                    queryText,
                    null
                    );

                storedQueries.Add(query);
            }
            else
            {
                // update query
                query.QueryText = queryText;
                query.Update();
            }
        }

        #endregion
    }
}
